﻿using System;
using System.Collections.Generic;
using System.Linq;
using FitNesseRunner;

namespace FitNesseRunnerTests
{
	public class FakeReflectionProvider : IReflectionProvider
	{
		private readonly List<string> _calledMethods = new List<string>();
		private readonly Dictionary<string, Func<IEnumerable<object>, object>> _methods = new Dictionary<string, Func<IEnumerable<object>, object>>();
		private Func<IEnumerable<object>, object> _constructor;

		public IEnumerable<string> CalledMethods
		{
			get { return _calledMethods; }
		}

		public object InstantiatedObject { get; private set; }

		public object CreateInstance(string className, IEnumerable<string> parameters)
		{
			if (_constructor == null)
				return null;
				
			InstantiatedObject = _constructor(parameters);
			return InstantiatedObject;
		}

		public object Invoke(object instance, string methodName, IEnumerable<string> parameters)
		{
			object result = null;
			Func<IEnumerable<object>, object> method;
			if (_methods.TryGetValue(methodName, out method))
				result = method(parameters);

			_calledMethods.Add(methodName);
			return result;
		}

		public void AddMethod(string methodName, Func<object, object> method)
		{
			AddMethod(methodName, args => method(args.SingleOrDefault()));
		}

		public void AddMethod(string methodName, Action<object> method)
		{
			AddMethod(methodName, (object arg) =>
			                      	{
			                      		method(arg);
			                      		return null;
			                      	});
		}

		public void AddMethod(string methodName, Func<IEnumerable<object>, object> method)
		{
			_methods.Add(methodName, method);
		}

		public void AddMethod(string methodName, Action<IEnumerable<object>> method)
		{
			AddMethod(methodName, args =>
			                      	{
			                      		method(args);
			                      		return null;
			                      	});
		}

		public void SetConstructor(string classname, Func<IEnumerable<object>, object> constructor)
		{
			_constructor = constructor;
		}
	}
}